package com.jinmdz.fmis.api.api.service;

import com.jinmdz.fmis.api.api.model.common.IdVersionData;
import com.jinmdz.fmis.api.api.model.funeral.negotiation.NegotiationAgentItem;
import com.jinmdz.fmis.api.api.model.funeral.negotiation.NegotiationDeadItem;
import com.jinmdz.fmis.api.api.model.funeral.negotiation.NegotiationMemberItem;
import com.jinmdz.fmis.api.api.model.photoarchival.PhotoArchivalAllData;
import com.jinmdz.fmis.api.api.model.photoarchival.PhotoArchivalItem;
import com.jinmdz.fmis.api.api.model.photoarchival.PhotoArchivalTypeData;
import com.jinmdz.fmis.api.base.BaseService;
import com.jinmdz.fmis.api.constant.FileConst;
import com.jinmdz.fmis.api.model.config.ConfigApp;
import com.jinmdz.fmis.api.model.config.dictionary.BusinessLogCode;
import com.jinmdz.fmis.api.model.config.dictionary.OperationLogCode;
import com.jinmdz.fmis.api.model.system.UserItem;
import com.jinmdz.fmis.api.wrapper.DictionaryWrapper;
import com.jinmdz.fmis.api.wrapper.DocumentWrapper;
import com.jinmdz.fmis.api.wrapper.OperationWrapper;
import com.jinmdz.fmis.api.wrapper.ToolWrapper;
import com.jinmdz.fmis.common.ext.StringBuilderExt;
import com.jinmdz.fmis.common.util.BeanUtil;
import com.jinmdz.fmis.common.util.DataUtil;
import com.jinmdz.fmis.core.base.BaseResult;
import com.jinmdz.fmis.core.exception.ActionException;
import com.jinmdz.fmis.core.util.JacksonUtil;
import com.jinmdz.fmis.dao.dao.*;
import com.jinmdz.fmis.dao.model.document.PhotoDocumentFileItem;
import com.jinmdz.fmis.dao.model.funeral.*;
import com.jinmdz.fmis.mapper.entity.DocumentFileEntity;
import com.jinmdz.fmis.mapper.entity.FuneralBusinessEntity;
import com.jinmdz.fmis.mapper.entity.FuneralBusinessLogEntity;
import com.jinmdz.fmis.mapper.mapper.DocumentFileMapper;
import com.jinmdz.fmis.mapper.mapper.FuneralBusinessMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.ArrayList;

import static com.jinmdz.fmis.api.constant.MessageConst.*;

/**
 * 拍照备案
 *
 * @author GuanKui
 * @date 2020/2/20 13:50
 */
@Service("photoArchivalService")
public class PhotoArchivalService extends BaseService {

    @Resource
    private FuneralBusinessDao funeralBusinessDao;

    @Resource
    private FuneralDeadDao funeralDeadDao;

    @Resource
    private FamilyMemberDao familyMemberDao;

    @Resource
    private FamilyAgentDao familyAgentDao;

    @Resource
    private DocumentFileDao documentFileDao;

    @Resource
    private DictionaryWrapper dictionaryWrapper;

    @Resource
    private DictionaryService dictionaryService;

    @Resource
    private ToolWrapper toolWrapper;

    @Resource
    private DocumentFileMapper documentFileMapper;

    @Resource
    private DocumentWrapper documentWrapper;

    @Resource
    private ConfigApp configApp;

    @Resource
    private OperationLogCode operationLogCode;

    @Resource
    private BusinessLogCode businessLogCode;

    @Resource
    private OperationWrapper operationWrapper;
    @Resource
    private FuneralBusinessMapper funeralBusinessMapper;

    /**
     * 根据businessCode加载拍照备案页面所有信息
     *
     * @param data 加载条件
     * @return
     * @author GuanKui
     * @date 2020/2/20 13:38
     */
    public BaseResult<PhotoArchivalItem> loadPhotoArchivalAll(PhotoArchivalAllData data) {
        String businessCode = data.getBusinessCode();
        // 通过业务编码获取殡葬信息
        FuneralBusinessViewItem funeralItem = funeralBusinessDao.getFuneralBusinessViewByBusinessCode(businessCode);
        if (DataUtil.isNull(funeralItem) || DataUtil.isNull(funeralItem.getId(), funeralItem.getVersion())) {
            throw exception(NO_FUNERAL_CODE);
        }

        // 创建返回实体
        PhotoArchivalItem loadItem = new PhotoArchivalItem();

        // 获取逝者信息
        FuneralDeadItem funeralDeadItem = funeralDeadDao.getFuneralDeadByBusinessCode(businessCode);
        if (funeralDeadItem != null) {
            NegotiationDeadItem deadItem = BeanUtil.copy2Bean(funeralDeadItem, new NegotiationDeadItem());
            // 设置字典文本
            dictionaryWrapper.resetDataText(deadItem);
            loadItem.setFuneralDead(deadItem);
        }

        // 获取家属信息
        FamilyMemberItem familyMemberItem = familyMemberDao.getFamilyMemberByBusinessCode(businessCode);
        if (familyMemberItem != null) {
            NegotiationMemberItem memberItem = BeanUtil.copy2Bean(familyMemberItem, new NegotiationMemberItem());
            dictionaryWrapper.resetDataText(memberItem);
            loadItem.setFamilyMember(memberItem);
        }

        // 获取承办人信息
        FamilyAgentItem familyAgentItem = familyAgentDao.getFamilyAgentByBusinessCode(businessCode);
        if (familyAgentItem != null) {
            NegotiationAgentItem agentItem = BeanUtil.copy2Bean(familyAgentItem, new NegotiationAgentItem());
            dictionaryWrapper.resetDataText(agentItem);
            loadItem.setFamilyAgent(agentItem);
        }

        // 加载字典数据
        loadItem.setDicts(dictionaryService.loadDictionaryMap(data.getDictTypeCodes()));

        // 获取拍照文件信息
        ArrayList<PhotoDocumentFileItem> documentFiles = documentFileDao.listPhotoDocumentFileByBusinessCode(businessCode);
        documentFiles.forEach(documentFile -> {
            String baseUrl = getBaserUrl();
            documentFile.setFilePath(baseUrl + documentFile.getFilePath());
            documentFile.setThumbPath(baseUrl + documentFile.getThumbPath());
        });

        // 设置字典文本
        dictionaryWrapper.resetDataText(documentFiles);
        loadItem.setDocumentFile(documentFiles);

        return successData(loadItem);
    }

    /**
     * 按拍照备案文档类型
     *
     * @param data 文档类型
     * @return
     * @author GuanKui
     * @date 2020/2/20 13:38
     */
    public BaseResult<ArrayList<PhotoDocumentFileItem>> loadPhotoArchivalByDocumentType(PhotoArchivalTypeData data) {
        String businessCode = data.getBusinessCode();
        // 通过业务编码获取殡葬信息
        FuneralBusinessViewItem funeralItem = funeralBusinessDao.getFuneralBusinessViewByBusinessCode(businessCode);
        if (DataUtil.isNull(funeralItem) || DataUtil.isNull(funeralItem.getId(), funeralItem.getVersion())) {
            throw exception(NO_FUNERAL_CODE);
        }

        // 获取拍照文件信息
        ArrayList<PhotoDocumentFileItem> documentFiles = documentFileDao.listPhotoDocumentFileByTypeCode(businessCode, data.getDocumentTypeCode());

        // 返回响应结果
        return successList(documentFiles);
    }

    /**
     * 保存拍照备案信息
     *
     * @param userItem              当前帐号
     * @param certificatesImageFile 证件照片文件,二进制文件流，证件照片或办理人照片至少要有一个
     * @param peopleImageFile       办理人照片文件,二进制文件流，证件照片或办理人照片至少要有一个
     * @return
     * @author GuanKui
     * @date 2020/2/20 13:38
     */
    @Transactional(rollbackFor = Exception.class)
    public BaseResult savePhotoArchival(UserItem userItem, PhotoArchivalTypeData data, MultipartFile certificatesImageFile, MultipartFile peopleImageFile) throws ActionException {
        if (certificatesImageFile == null && peopleImageFile == null) {
            throw exception("证件照片或办理人照片至少要有一个");
        }

        String businessCode = data.getBusinessCode();
        // 通过业务编码获取殡葬信息
        FuneralBusinessViewItem funeralItem = funeralBusinessDao.getFuneralBusinessViewByBusinessCode(businessCode);
        if (DataUtil.isNull(funeralItem) || DataUtil.isNull(funeralItem.getId(), funeralItem.getVersion())) {
            throw exception(NO_FUNERAL_CODE);
        }

        //公用随机码
        String randomCode = DataUtil.getUUID();

        // 保存证件照片
        saveImageFiles(userItem, funeralItem, data, certificatesImageFile, FileConst.FileCode.Image_Certificates, randomCode);

        // 保存办理人照片
        saveImageFiles(userItem, funeralItem, data, peopleImageFile, FileConst.FileCode.Image_People, randomCode);

        PhotoArchivalAllData photoArchivalAllData = new PhotoArchivalAllData();
        photoArchivalAllData.setBusinessCode(businessCode);

        return loadPhotoArchivalAll(photoArchivalAllData);
    }

    /**
     * 保存拍照备案信息
     *
     * @param userItem                  当前帐号
     * @param certificatesImageBaseFile 证件照片文件,base64字符串，证件照片或办理人照片至少要有一个
     * @param peopleImageBaseFile       办理人照片文件,base64字符串，证件照片或办理人照片至少要有一个
     * @return
     * @author Gaoxiangliang
     * @date 2020/3/04 13:38
     */
    @Transactional(rollbackFor = Exception.class)
    public BaseResult<PhotoArchivalItem> savePhotoArchival(UserItem userItem, PhotoArchivalTypeData data, String certificatesImageBaseFile, String peopleImageBaseFile) throws ActionException {
        if (certificatesImageBaseFile == null && peopleImageBaseFile == null) {
            throw exception("证件照片或办理人照片至少要有一个");
        }

        String businessCode = data.getBusinessCode();
        // 通过业务编码获取殡葬信息
        FuneralBusinessViewItem funeralItem = funeralBusinessDao.getFuneralBusinessViewByBusinessCode(businessCode);
        if (DataUtil.isNull(funeralItem) || DataUtil.isNull(funeralItem.getId(), funeralItem.getVersion())) {
            throw exception(NO_FUNERAL_CODE);
        }

        //公用随机码
        String randomCode = DataUtil.getUUID();

        // 保存证件照片
        saveBaseStringToImageFiles(userItem, funeralItem, data, certificatesImageBaseFile, FileConst.FileCode.Image_Certificates, randomCode);

        // 保存办理人照片
        saveBaseStringToImageFiles(userItem, funeralItem, data, peopleImageBaseFile, FileConst.FileCode.Image_People, randomCode);

        PhotoArchivalAllData photoArchivalAllData = new PhotoArchivalAllData();
        photoArchivalAllData.setBusinessCode(businessCode);

        return loadPhotoArchivalAll(photoArchivalAllData);
    }
    /**
     * 保存人证核验照片
     *
     * @param userItem                  当前帐号
     * @param certificatesImageBaseFile 证件照片文件,base64字符串，证件照片或办理人照片至少要有一个
     * @param peopleImageBaseFile       办理人照片文件,base64字符串，证件照片或办理人照片至少要有一个
     * @return
     * @author Gaoxiangliang
     * @date 2020/3/04 13:38
     */
    @Transactional(rollbackFor = Exception.class)
    public BaseResult<PhotoArchivalItem> saveOneCardToCheck(UserItem userItem, PhotoArchivalTypeData data, String certificatesImageBaseFile, String peopleImageBaseFile) throws ActionException {
        if (certificatesImageBaseFile == null || peopleImageBaseFile == null) {
            throw exception("证件照片和家属照片缺一不可");
        }

        String businessCode = data.getBusinessCode();
        // 通过业务编码获取殡葬信息
        FuneralBusinessViewItem funeralItem = funeralBusinessDao.getFuneralBusinessViewByBusinessCode(businessCode);
        if (DataUtil.isNull(funeralItem) || DataUtil.isNull(funeralItem.getId(), funeralItem.getVersion())) {
            throw exception(NO_FUNERAL_CODE);
        }

        //公用随机码
        String randomCode = DataUtil.getUUID();

        // 保存证件照片
        saveBaseStringToImageFiles(userItem, funeralItem, data, certificatesImageBaseFile, FileConst.FileCode.Image_Certificates_Check, randomCode);

        // 保存办理人照片
        saveBaseStringToImageFiles(userItem, funeralItem, data, peopleImageBaseFile, FileConst.FileCode.Image_People_Check, randomCode);
        //验证是否通过  ,0未验证，1：已验证
        if(null!=data.getAsRecognition()){
            FamilyMemberItem familyMemberItem=familyMemberDao.getFamilyMemberByBusinessCode(businessCode);
            if(null!=familyMemberItem && null !=familyMemberItem.getId() &&null!=familyMemberItem.getVersion() && null!=familyMemberItem.getAsRecognition()&& null!=userItem){
                //更新人证核验
                familyMemberDao.updateFamilyMemberByBusinessCode(familyMemberItem.getId(),familyMemberItem.getAsRecognition(),userItem.getId(),familyMemberItem.getVersion());
            }
        }
        PhotoArchivalAllData photoArchivalAllData = new PhotoArchivalAllData();
        photoArchivalAllData.setBusinessCode(businessCode);

        return loadPhotoArchivalAll(photoArchivalAllData);
    }
    /**
     * 保存遗体抓拍备案
     *
     * @param userItem                  当前帐号
     * @param bodyImageBaseFileOne      逝者抓拍照片文件一,base64字符串，证件照片或办理人照片至少要有一个
     * @param bodyImageBaseFileTwo      逝者抓拍照片文件二,base64字符串，证件照片或办理人照片至少要有一个
     * @param bodyImageBaseFileThree    逝者抓拍照片文件三,base64字符串，证件照片或办理人照片至少要有一个
     * @return
     * @author Gaoxiangliang
     * @date 2020/3/04 13:38
     */
    @Transactional(rollbackFor = Exception.class)
    public BaseResult<PhotoArchivalItem> saveBodyPhotoForRecord(UserItem userItem, PhotoArchivalTypeData data, String bodyImageBaseFileOne, String bodyImageBaseFileTwo,String bodyImageBaseFileThree) throws ActionException {
        if (bodyImageBaseFileOne == null && bodyImageBaseFileTwo == null && bodyImageBaseFileThree==null ) {
            throw exception("逝者抓拍照片至少要有一个");
        }

        String businessCode = data.getBusinessCode();
        // 通过业务编码获取殡葬信息
        FuneralBusinessViewItem funeralItem = funeralBusinessDao.getFuneralBusinessViewByBusinessCode(businessCode);
        if (DataUtil.isNull(funeralItem) || DataUtil.isNull(funeralItem.getId(), funeralItem.getVersion())) {
            throw exception(NO_FUNERAL_CODE);
        }

        //公用随机码
        String randomCode = DataUtil.getUUID();
        if(null!=bodyImageBaseFileOne && ! "" .equals(bodyImageBaseFileOne)){
            // 保存遗体抓拍照片1
            saveBaseStringToImageFiles(userItem, funeralItem, data, bodyImageBaseFileOne, FileConst.FileCode.Image_Body_One, randomCode);
        }
        if(null!=bodyImageBaseFileTwo && ! "" .equals(bodyImageBaseFileTwo)){
            // 保存遗体抓拍照片2
            saveBaseStringToImageFiles(userItem, funeralItem, data, bodyImageBaseFileTwo, FileConst.FileCode.Image_Body_Two, randomCode);
        }
        if(null!=bodyImageBaseFileThree && ! "" .equals(bodyImageBaseFileThree)){
            // 保存遗体抓拍照片3
            saveBaseStringToImageFiles(userItem, funeralItem, data, bodyImageBaseFileThree, FileConst.FileCode.Image_Body_Three, randomCode);
        }
        PhotoArchivalAllData photoArchivalAllData = new PhotoArchivalAllData();
        photoArchivalAllData.setBusinessCode(businessCode);

        return loadPhotoArchivalAll(photoArchivalAllData);
    }

    /**
     * 图片保存
     *
     * @param userItem    当前帐号
     * @param funeralItem 殡葬业务
     * @param data        请求数据
     * @param imageFile   上传文件
     * @param fileCode    图片编码
     * @param randomCode  操作随机码
     * @return
     * @author GuanKui
     * @date 2020/2/20 16:35
     */
    private void saveImageFiles(UserItem userItem, FuneralBusinessViewItem funeralItem, PhotoArchivalTypeData data, MultipartFile imageFile, String fileCode, String randomCode) throws ActionException {
        if (imageFile == null) {
            return;
        }

        DocumentFileEntity entity = documentWrapper.saveImageFile(imageFile);
        if (entity == null) {
            throw exception("接收图片错误");
        }

        // 生成图片实体
        entity.setTableName(toolWrapper.getTableName(FuneralBusinessEntity.class))
                .setTableId(funeralItem.getId())
                .setBusinessCode(data.getBusinessCode())
                .setDocumentTypeCode(data.getDocumentTypeCode())
                .setFileCode(fileCode)
                .setRandomCode(randomCode);

        // 赋值修改人等信息
        entity.setFuneralParlourCode(configApp.getFuneralParlourCode())
                .setCreateUserId(userItem.getId())
                .setModifiedUserId(userItem.getId());

        // 插入图片文件
        documentFileMapper.insertDocumentFile(entity);

        // 判断保存信息结果
        if (DataUtil.invalid(entity.getId())) {
            throw exception("保存打印记录失败");
        }

        // 添加日志记录
        saveImageFilesLog(userItem, funeralItem, entity);
    }

    /**
     * 图片保存
     *
     * @param userItem     当前帐号
     * @param funeralItem  殡葬业务
     * @param data         请求数据
     * @param baseImageStr base64图像字符串
     * @param fileCode     图片编码
     * @param randomCode   操作随机码
     * @return
     * @author GaoxiangLiang
     * @date 2020/2/20 16:35
     */
    private void saveBaseStringToImageFiles(UserItem userItem, FuneralBusinessViewItem funeralItem, PhotoArchivalTypeData data, String baseImageStr, String fileCode, String randomCode) throws ActionException {
        if (baseImageStr == null) {
            return;
        }

        DocumentFileEntity entity = documentWrapper.saveBaseImageFile(".jpg", baseImageStr);
        if (entity == null) {
            throw exception("接收图片错误");
        }

        // 生成图片实体
        entity.setTableName(toolWrapper.getTableName(FuneralBusinessEntity.class))
                .setTableId(funeralItem.getId())
                .setBusinessCode(data.getBusinessCode())
                .setDocumentTypeCode(data.getDocumentTypeCode())
                .setFileCode(fileCode)
                .setRandomCode(randomCode);

        // 赋值修改人等信息
        entity.setFuneralParlourCode(configApp.getFuneralParlourCode())
                .setCreateUserId(userItem.getId())
                .setModifiedUserId(userItem.getId());

        // 插入图片文件
        documentFileMapper.insertDocumentFile(entity);

        // 判断保存信息结果
        if (DataUtil.invalid(entity.getId())) {
            throw exception("保存打印记录失败");
        }

        // 添加日志记录
        saveImageFilesLog(userItem, funeralItem, entity);
    }

    /**
     * 添加上传图片日志记录
     *
     * @param userItem    当前帐号
     * @param funeralItem 当前业务
     * @param entity      图片信息
     * @return
     * @author LiCongLu
     * @date 2020-02-26 09:36
     */
    private void saveImageFilesLog(UserItem userItem, FuneralBusinessViewItem funeralItem, DocumentFileEntity entity) throws ActionException {

        // 添加业务日志及操作日志
        String businessCode = funeralItem.getBusinessCode();
        Integer typeCode = businessLogCode.getPhotoArchival();
        FuneralBusinessLogEntity businessLogEntity = operationWrapper.businessLog(userItem, businessCode, typeCode);

        // 操作日志字符串
        StringBuilderExt builder = new StringBuilderExt();
        builder.format("上传图片，业务编码[{0}]，逝者姓名[{1}]，操作人员[{2}]"
                , businessCode, funeralItem.getDeadName()
                , userItem.getFullName());

        // 添加日志
        operationWrapper.operationLog(userItem, businessLogEntity, operationLogCode.getPhotoArchival(), builder.toString(), null, null, JacksonUtil.obj2Json(entity));
    }

    /**
     * 从documentFile表中删除指定id的拍照图片记录
     *
     * @param data 主键和版本号
     * @return
     * @author GaoXiangLiang
     * @date 2020-05-11 14:38
     */
    @Transactional(rollbackFor = Exception.class)
    public BaseResult deletePhotoArchivalWithId(UserItem userItem, IdVersionData data) throws ActionException {
        // 获得图片实体
        DocumentFileEntity entity = documentFileMapper.getDocumentFileById(data.getId());
        if (DataUtil.isNull(entity) || DataUtil.isNull(entity.getId(), entity.getVersion())) {
            return failure("主键错误，不存在此拍照备案");
        }
        //验证版本
        if (!DataUtil.equals(entity.getVersion(), data.getVersion())) {
            throw exception(VERSION_ERROR);
        }

        // 验证拍照备案版本
        if (!DataUtil.equals(entity.getVersion(), data.getVersion())) {
            return failure(versionError("拍照备案"));
        }
        //业务编码
        String businessCode = entity.getBusinessCode();
        if (DataUtil.isNull(businessCode)) {
            return failure(versionError("业务编码不存在"));
        }
        // 通过业务编码获取殡葬信息
        FuneralBusinessViewItem funeralItem = funeralBusinessDao.getFuneralBusinessViewByBusinessCode(businessCode);
        if (DataUtil.isNull(funeralItem) || DataUtil.isNull(funeralItem.getId(), funeralItem.getVersion())) {
            throw exception(NO_FUNERAL_CODE);
        }
        //删除拍照记录文件
        deleteBaseStringOfImageFiles(userItem, funeralItem, data);
        return success("删除完成");
    }

    /**
     * 图片删除
     *
     * @param userItem      当前帐号
     * @param idVersionData id和版本数据
     * @return
     * @author GaoxiangLiang
     * @date 2020/2/20 16:35
     */
    private void deleteBaseStringOfImageFiles(UserItem userItem, FuneralBusinessViewItem funeralItem, IdVersionData idVersionData) throws ActionException {
        if (idVersionData == null) {
            return;
        }
        // 获得图片实体
        DocumentFileEntity entity = documentFileMapper.getDocumentFileById(idVersionData.getId());
        if (entity == null) {
            throw exception(NO_DATA);
        }
        //验证版本
        if (!DataUtil.equals(entity.getVersion(), idVersionData.getVersion())) {
            throw exception(VERSION_ERROR);
        }
        // 删除实体文件(物理文件)
        documentWrapper.deleteImageFile(entity);
        // 删除图片的实际图片记录数据
        documentFileMapper.deletedForDocumentFile(entity.getId(), userItem.getId(), entity.getVersion());
        // 添加日志记录
        deleteImageFilesLog(userItem, funeralItem, entity);
    }

    /**
     * 添加上传图片日志记录
     *
     * @param userItem    当前帐号
     * @param funeralItem 当前业务
     * @param entity      图片信息
     * @return
     * @author GaoXiangLiang
     * @date 2020-05-11 14:36
     */
    private void deleteImageFilesLog(UserItem userItem, FuneralBusinessViewItem funeralItem, DocumentFileEntity entity) throws ActionException {

        // 添加业务日志及操作日志
        String businessCode = funeralItem.getBusinessCode();
        Integer typeCode = businessLogCode.getPhotoArchival();
        FuneralBusinessLogEntity businessLogEntity = operationWrapper.businessLog(userItem, businessCode, typeCode);

        // 操作日志字符串
        StringBuilderExt builder = new StringBuilderExt();
        builder.format("删除图片，业务编码[{0}]，逝者姓名[{1}]，操作人员[{2}]"
                , businessCode, funeralItem.getDeadName()
                , userItem.getFullName());

        // 添加日志
        operationWrapper.operationLog(userItem, businessLogEntity, operationLogCode.getPhotoArchival(), builder.toString(), null, null, JacksonUtil.obj2Json(entity));
    }

}
